Analyser les projets TypeScript avec Moose
Ce tutoriel vous expliquera une démarche pour importer dans Moose un modèle d’un projet TypeScript et d’en faire une analyse.
Introduction
Ce tutoriel explique comment analyser des projets TypeScript avec Moose dans le cadre du cours MGL843 à l’ÉTS. Il s’inspire du tutoriel Analyzing Java with Moose 8.
Rappel des principes
Les principes importants de ce tutoriel sont illustrés dans la figure ci-dessus. Nous les explorerons à différentes étapes du tutoriel. Le but est de vous guider à travers ces étapes, qui représentent un processus de base pour effectuer une analyse (empirique) dans le cadre du cours.
Obtenir le code source d’un projet TypeScript à analyser
- Trouvez un projet en TypeScript à analyser, par exemple sur https://github.com/Chuzzy/Emojiopoly.
- Clonez le projet avec Git pour obtenir le code sur votre machine locale, par exemple dans le répertoire
GitHub/Emojiopoly.
Installer l’importateur ts2famix
ts2famixest un logiciel pour node.js. Installer node et npm- Ouvrez un terminal Git Bash dans VS Code.
- ⚠ Utilisez un environnement de commande Git Bash (même sur Windows).
- ⚠ VS Code sur Windows démarre un terminal avec Powershell. Pour ce tutoriel, vous devez avoir un terminal Git Bash. Consultez comment spécifier un autre terminal shell dans VS Code.
- Les commandes Bash sont similaires à des commandes dans Linux :
ls,cd, etc. - Les chemins du système de fichiers sont formatés comme sous Linux, ce qui signifie que vous devez utiliser la barre oblique (
/) au lieu de la barre oblique inverse (\, utilisée sous Windows) dans les chemins. ts2famixest une bibliothèque (package)npm. Installez node et npm.
- Installez l’importateur
ts2famixavec la commandenpm install -g ts2famixdans le terminal Git Bash.
Générer un modèle du projet
Utilisez la même fenêtre Bash que celle utilisée précédemment pour installer l’outil
ts2famix.Si votre répertoire de travail actuel est le même que celui du projet, par exemple,
GitHub/Emojiopoly, vous pouvez taper :ts2famix -i tsconfig.json -o emojiopoly-model.jsonLe fichier
tsconfig.jsonest en faitGitHub/Emojiopoly/tsconfig.json(c’est dans le répertoire de travail). Ce fichier décrit le projet Emojiopoly (typiquement les projets TypeScript ont ce genre de fichier).ts2famixutilise ce fichier pour trouver le code source pour faire le modèle. Si votre projet n’a pas detsconfig.json, il est toujours possible d’importer des fichiers avec l’option-i "/chemin/vers/fichiers/**/*.ts"(notez bien l’utilisation de"autour de l’expression !) ce qui va trouver tous les fichiers*.tsdans l’arborescence spécifié avant le**/. Il s’agit d’un glob pattern pour spécifier des ensembles de fichiers à traiter. Le fichieremojiopoly-model.jsonest le modèle Famix (en format JSON) du projet TypeScript généré par l’importateur. Dans les étapes suivantes, vous allez charger ce modèle dans Moose.
Configurer l’image Moose (survol)
Il y a plusieurs étapes à suivre pour importer un modèle dans Moose. Une fois cette étape terminée, vous pourrez réutiliser l’image pour effectuer des analyses.
- Créez une image Moose avec Pharo Launcher. Pour la version actuelle de
ts2famix, il faut utiliser le template Moose Suite 11 (stable). - Chargez le métamodèle
FamixTypeScriptdans Moose.
Créer une image Moose Suite 10 dans Pharo
- Installez Pharo Launcher et lancez-le.
- Ajoutez une image à partir du template Moose Suite 11 (stable). ## Charger le métamodèle FamixTypeScript dans Moose
Par défaut, Moose ne possède pas de métamodèle pour le langage TypeScript. Vous devez donc charger le métamodèle FamixTypeScript dans Moose.
Charger avec un script Baseline
Sélectionnez l’image Moose Suite 11 (stable) (créée à l’étape précédente) dans Pharo Launcher et démarrez-la (bouton Launch).
Dans Pharo, tapez CTRL-O CTRL-W pour ouvrir une fenêtre Moose Playground.
Dans cette fenêtre, tapez (collez) le texte suivant :
Metacello new githubUser: 'fuhrmanator' project: 'FamixTypeScript' commitish: 'master' path: 'src'; baseline: 'FamixTypeScript'; loadAppuyez sur CTRL-SHIFT-G (Do it all and go) pour exécuter la commande. Le métamodèle devrait être chargé à la fin.
Charger le modèle du projet TypeScript dans Moose
Maintenant que Moose connaît le métamodèle FamixTypeScript, vous pouvez charger un modèle de programme TypeScript créé par l’outil ts2famix.
- Vous pouvez faire glisser le fichier
emojiopoly-model.jsonet le déposer dans la fenêtre où s’exécute Moose 11. Une boîte de dialogue s’ouvrira pour vous demander de confirmer que vous souhaitez importer le modèle dans Moose. - Menu Moose > Models browser pour vérifier que le modèle est chargé dans Moose. Le nom emojiopoly-model (ou le nom du fichier .json) devrait être dans la liste de Models de la fenêtre.
Facultatif : automatiser le chargement d’un modèle
Pour automatiser le chargement du modèle dans Moose, vous pouvez utiliser le code suivant en Pharo.
'emojiopoly-model.json' asFileReference readStreamDo:
[ :stream | model := FamixTypeScriptModel new
importFromJSONStream: stream. model install ].Effectuer une analyse
Cette étape n’est pas une analyse empirique complète, car il n’y a pas de questions de recherche ou de validation d’hypothèses, etc. Cependant, vous pouvez apprendre comment accéder aux informations dans un modèle de programme TypeScript à travers Moose.
- À partir de la fenêtre Models browser, sélectionnez emojiopoly-model dans la liste.
- Cliquez sur le bouton Inspect (icône avec des lunettes).
- Une nouvelle fenêtre Moose Inspector apparaîtra.
- Cliquez sur Card dans la liste de gauche.
- Vous verrez une sous-fenêtre a FamixTypeScriptClass (Card) à gauche.
- Cliquez sur l’onglet SourceText en haut de cette sous-fenêtre pour voir le code source de la classe.
- Cliquez sur l’onglet Moose Properties pour voir les propriétés Moose de cette classe.
Faire une requête simple
Dans une fenêtre Playground, exécutez le code suivant :
"Get the emojiopoly model (first in Moose panel)"
tsModel := MooseModel root first.
"Find all classes that have 100 or more lines of code"
bigClasses := tsModel allModelClasses
select: [ :each |
each numberOfLinesOfCode >= 100 ]Le résultat devrait généralement inclure une seule classe, MonopolyGame. Vous pouvez la sélectionner et consulter son code source pour vérifier.
Dans l’onglet Navigation, vous pouvez également voir ses méthodes, ses attributs, etc.
Pour obtenir une liste de méthodes longues (contenant 20 lignes ou plus) dans le projet, exécutez ce script :
"Get the emojiopoly model (first in Moose panel)"
tsModel := MooseModel root first.
"Find all methods that have 20 or more lines of code"
longMethods := tsModel allMethods
select: [ :each |
each numberOfLinesOfCode >= 20 ]Pour trouver la classe à laquelle chaque méthode appartient, consultez la propriété parentType dans la navigation.
Requêtes spécifiques à TypeScript
Que faire si vous souhaitez trouver tous les Decorators (un élément spécifique à TypeScript) dans un projet ? Malheureusement, il n’existe pas (encore) de méthode tsModel allDecorators pour les modèles TypeScript. La solution consiste à utiliser tsModel allMatching: FamixTypeScriptDecorator. En effet, la méthode allMatching: permet de trouver tous les éléments d’une entité spécifique. Vous pouvez voir les noms des éléments du métamodèle TypeScript dans la visualisation SVG du dépôt du métamodèle. Les éléments sont affichés comme des classes UML en bleu clair, par exemple, Module, Decorator, etc. Notez que vous devez ajouter le préfixe FamixTypeScript au nom de l’élément, par exemple, FamixTypeScriptModule, FamixTypeScriptDecorator, etc.
Faire une visualisation des classes avec Roassal 3
Roassal 3 est une bibliothèque de visualisation puissante (et complexe) dans Pharo. Vous pouvez vous inspirer d’une visualisation en Roassal (une bibliothèque de visualisation dans Pharo) pour représenter visuellement les classes dans un modèle Moose :
"La variable classes contient les classes que nous souhaitons visualiser"
classes := MooseModel root first allModelClasses.
"Un canvas est un conteneur de formes graphiques"
c := RSCanvas new.
"Chaque classe est représentée comme une boîte"
classes do: [ :aClass | c add: (RSBox new model: aClass) ].
"La largeur de chaque classe indique le nombre de variables définies dans la classe"
RSNormalizer width shapes: c shapes; from: 6; to: 20;
normalize: #numberOfAttributes.
"La hauteur de chaque classe représente le nombre de méthodes"
RSNormalizer height shapes: c shapes; normalize: #numberOfMethods.
"La couleur d'une classe passe du gris au rouge, indiquant le nombre de lignes de code"
RSNormalizer color shapes: c shapes;
from: Color gray; to: Color red; normalize: #numberOfLinesOfCode.
"Les lignes verticales indiquent la relation d'héritage"
RSLineBuilder orthoVertical
canvas: c; withVerticalAttachPoint; color: Color lightGray;
connectFrom: #superclass.
"Utiliser une disposition en arbre pour localiser adéquatement les classes"
RSTreeLayout on: c nodes.
"Nous rendons toutes les classes déplaçables et avec une fenêtre contextuelle"
c nodes @ RSDraggable @ RSPopup.
"La visualisation entière est zoomable, déplaçable, et les formes peuvent être recherchées"
c @ RSCanvasController.Cette visualisation représente les classes sous forme de rectangles. Chaque rectangle a trois dimensions :
- La couleur de chaque rectangle représente le nombre de lignes de code. Le gris signifie un nombre relativement faible de lignes de code, tandis que le rouge indique un nombre relativement élevé de lignes de code. La variation de couleur est gérée par la classe
RSNormalizer. - La hauteur de chaque rectangle représente le nombre de méthodes.
- La largeur de chaque rectangle représente le nombre d’attributs.
La visualisation obtient les données de chaque élément Moose à travers les propriétés, par exemple #numberOfAttributes, #numberOfMethods et #numberOfLinesOfCode. Au fait, ce sont des méthodes (accesseurs) des éléments Famix, par exemple FamixTypeScriptClass qui fournissent les valeurs. On peut trouver d’autres propriétés dans l’onglet Moose Properties de ces éléments.
Avec le projet emojiopoly, on voit bien que la classe MonopolyGame a beaucoup de méthodes (sa hauteur) et aussi beaucoup de lignes de code (sa couleur rouge).
La syntaxe avec le dièse utilisée à la ligne 9, normalize: #numberOfAttributes, est un raccourci syntaxique pour une expression de bloc plus longue : normalize: [:element | element numberOfAttributes ]. Parfois, vous voudrez effectuer un calcul sur la valeur utilisée dans la visualisation, par exemple en la combinant avec un autre attribut comme le nombre de receivingInvocations. Dans ce cas, vous feriez normalize: [:element | element numberOfAttributes + element receivingInvocations size ].
La disposition (RSTreeLayout) permet également de visualiser la hiérarchie des classes en ce qui concerne l’héritage. Cependant, le projet emojiopoly n’utilise pas l’héritage en TypeScript, donc aucune arborescence n’est visible dans la visualisation.
Conclusion
Vous avez effectué les étapes nécessaires pour analyser des programmes en TypeScript à l’aide de l’outil Moose dans Pharo, en utilisant un métamodèle Famix et un importateur (ts2famix).
Il est important de comprendre que le métamodèle influence également d’autres éléments du processus, notamment l’importateur et le fichier .json qu’il génère (le modèle).
L’importateur ts2famix dépend du métamodèle FamixTypeScript, car il transforme un programme TypeScript en modèle Famix, selon la structure du métamodèle.